package com.niiwoo.civet.trade.service.local.loan.creditaduit;

import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.dangdang.ddframe.rdb.sharding.api.HintManager;
import com.dangdang.ddframe.rdb.sharding.hint.HintManagerHolder;
import com.niiwoo.civet.trade.dao.entity.Project;
import com.niiwoo.civet.trade.dao.entity.ProjectFlowExecuteRuntime;
import com.niiwoo.civet.trade.enums.LoanNodeTypeEnum;
import com.niiwoo.civet.trade.enums.ProjectFlowExecuteRuntimeNodeStatusEnum;
import com.niiwoo.civet.trade.enums.ProjectStatusEnum;
import com.niiwoo.civet.trade.enums.ProjectTypeEnum;
import com.niiwoo.civet.trade.service.local.loan.TianchengModelParseService;
import com.niiwoo.civet.user.dto.response.credit.BasicInfoDTO;
import com.niiwoo.civet.user.dto.response.credit.ContactPersonInfoDTO;
import com.niiwoo.civet.user.dto.response.credit.CreditScoreCardDTO;
import com.niiwoo.civet.user.dto.response.credit.TianchengCreditBaseInfoResponseDTO;
import com.niiwoo.civet.user.dto.response.credit.WorkInfoDTO;
import com.niiwoo.civet.user.enums.TianchengCallbackEventEnum;
import com.niiwoo.civet.user.service.TianchengDataDubboService;
import com.niiwoo.civet.user.service.UserForbidDubboService;
import com.niiwoo.tripod.tiancheng.component.TianchengAgainstFakeV2Service;
import com.niiwoo.tripod.tiancheng.enums.AgainstFakeErrorCodeEnum;
import com.niiwoo.tripod.tiancheng.enums.AntifraudFromSourceEnum;
import com.niiwoo.tripod.tiancheng.enums.FunctionCodeEnum;
import com.niiwoo.tripod.tiancheng.request.afp.CreditAduitAgainLoanRequest;
import com.niiwoo.tripod.tiancheng.request.afp.CreditAduitAgainRequest;
import com.niiwoo.tripod.tiancheng.request.afp.CreditAduitFirstLoanRequest;
import com.niiwoo.tripod.tiancheng.request.afp.CreditAduitRequest;
import com.niiwoo.tripod.tiancheng.request.afp.KaDaiRepairServiceRequest;
import com.niiwoo.tripod.tiancheng.response.common.AgainstFakeV2Response;

import lombok.extern.slf4j.Slf4j;

/**
 * 消费贷信审
 *  
 * @author kevin.jia
 * @create 2018年11月27日 下午5:56:58
 */
@Slf4j
@Service
public class ConsumeLoanCreditAduitService extends AbstractCreditAuditService {
	
	@Autowired
    private TianchengAgainstFakeV2Service tianchengAgainstFakeV2Service;
	
	@Reference(version = "1.0.0")
	private TianchengDataDubboService tianchengDataDubboService;
	
	@Reference(version = "1.0.0")
	private UserForbidDubboService userForbidDubboService;
	
    protected boolean isAgainLoan = true;

	/**
	 * 调用天称用户信审模型
	 * 
	 * @param userId
	 * @param projectId
	 * @param flowExecuteId
	 */
	@Override
    public void toRequestAutoAuditModel(String userId, Long projectId, Long flowExecuteId) {
		// 强制走主库
		if (!HintManagerHolder.isMasterRouteOnly()) {
			HintManagerHolder.clear();
			HintManager hintManager = HintManager.getInstance();
			hintManager.setMasterRouteOnly();
		}
		
    	ProjectFlowExecuteRuntime projectFlowExecuteRuntime = projectFlowExecuteRuntimeMapperExt.selectByPrimaryKey(flowExecuteId);
		if (projectFlowExecuteRuntime == null) {
			log.info("标准化消费借用户信审，执行流程不存在，ProjectId：{}, flowExecuteId:{}", projectId, flowExecuteId);			
			return;
		}

		LoanNodeTypeEnum loanNodeTypeEnum = LoanNodeTypeEnum.enumof(projectFlowExecuteRuntime.getNodeId());
		if (!LoanNodeTypeEnum.LOAN_SYSTEM_AUDIT.equals(loanNodeTypeEnum)) {
			log.info("标准化消费借用户信审，当前节点不在用户信审核，ProjectId：{}, flowExecuteId:{}", projectId, flowExecuteId);
			return;
		}
		
    	Project project = projectCommonService.queryProjectBasicInfo(projectId);
        if (project == null) {
        	log.info("标准化消费借用户信审，标的不存在，ProjectId：{}, flowExecuteId:{}", projectId, flowExecuteId);
            projectFlowExecuteService.failEndProjectFlowExecute(flowExecuteId, LoanNodeTypeEnum.LOAN_SYSTEM_AUDIT, "标的不存在");
            return;
        }
        
		if (!project.getStatus().equals(ProjectStatusEnum.CHECKING.getStatus())) {
			log.info("标准化消费借用户信审，标的不在审核中状态，ProjectId：{}, flowExecuteId:{}，status:{}", projectId, flowExecuteId, project.getStatus());
			return;
		}
        
		// 重试超过三次时直接流标
        if (projectFlowExecuteRuntime.getRetryTimes() > 3) {
			log.info("标准化消费借用户信审重试次数超过三次，流标处理，ProjectId：{}, flowExecuteId:{}", projectId, flowExecuteId);        	
			projectFlow(project.getProjectId(), flowExecuteId, LoanNodeTypeEnum.LOAN_SYSTEM_AUDIT, false, "重试3次调用天秤信审接口失败");
			return;
		}

		// 是否首借用户
		isAgainLoan = loanAntiFraudLocalService.firstLoan(userId);
        
    	try {
    		// 构建请求参数
    		AgainstFakeV2Response againstFakeV2Response = null;
    		String orderId = String.valueOf(snowflakeIdWorker.nextId());
    		if (isAgainLoan) {
    			CreditAduitAgainRequest creditAduitAgainRequest = bulidCreditAduitAgainRequestParam(userId, projectFlowExecuteRuntime.getFlowExecuteId(), project, orderId);
        		log.info("标准化消费借复借用户信审，请求参数：{}", JSON.toJSONString(creditAduitAgainRequest));
        		CompletableFuture<AgainstFakeV2Response> completableFuture = tianchengAgainstFakeV2Service.consumeLoanCreditAduitAgain(creditAduitAgainRequest);
        		againstFakeV2Response = completableFuture.get();
        		log.info("标准化消费借复借用户信审，返回结果：{}", JSON.toJSONString(againstFakeV2Response));      			
    		} else {
    			CreditAduitRequest creditAduitRequest = bulidCreditAduitRequestParam(userId, projectFlowExecuteRuntime.getFlowExecuteId(), project, orderId);
        		log.info("标准化消费借首借用户信审，请求参数：{}", JSON.toJSONString(creditAduitRequest));
        		CompletableFuture<AgainstFakeV2Response> completableFuture = tianchengAgainstFakeV2Service.consumeLoanCreditAduit(creditAduitRequest);
        		againstFakeV2Response = completableFuture.get();
        		log.info("标准化消费借首借用户信审，返回结果：{}", JSON.toJSONString(againstFakeV2Response));
    		}
    		
    		// 返回结果处理
	    	if (againstFakeV2Response != null && AgainstFakeErrorCodeEnum.SUCCESS.getErrorCode() == againstFakeV2Response.getCode().intValue()) {
	    		// 新增天秤请求记录
				addTianChengRequestRecord(userId, projectId, flowExecuteId, orderId);
				// 下一个流程节点：天秤信审回调
				projectFlowExecuteService.initNextStepProjectFlowExecute(flowExecuteId, LoanNodeTypeEnum.LOAN_SYSTEM_AUDIT, LoanNodeTypeEnum.LOAN_SYSTEM_AUDIT_BACK, null);
			} else {
				projectFlowExecuteService.updateProjectFlowExecuteRuntime(flowExecuteId, LoanNodeTypeEnum.LOAN_SYSTEM_AUDIT, ProjectFlowExecuteRuntimeNodeStatusEnum.EXCEPTION, "天秤信审服务异常");
			}
    	} catch (Exception e) {
    		log.error("标准化消费借用户信审异常，ProjectId：{}, flowExecuteId:{}", projectId, flowExecuteId, e);
    		projectFlowExecuteService.updateProjectFlowExecuteRuntime(flowExecuteId, LoanNodeTypeEnum.LOAN_SYSTEM_AUDIT, ProjectFlowExecuteRuntimeNodeStatusEnum.EXCEPTION, e.getMessage());
    	}
    }

	@Override
	public AgainstFakeV2Response firstLoan(CreditAduitFirstLoanRequest request) throws Exception {
		return null;
	}

	@Override
	public AgainstFakeV2Response againLoan(CreditAduitAgainLoanRequest request) throws Exception {
		return null;
	}

	@Override
	public AgainstFakeV2Response repair(KaDaiRepairServiceRequest request) throws Exception {
		return null;
	}

	@Override
	public ProjectTypeEnum getProjectType() {
		return ProjectTypeEnum.CONSUME_LOAN;
	}
	
	@Override
	public FunctionCodeEnum getFunctionCode() {
		return isAgainLoan ? FunctionCodeEnum.LIBRA_CREDIT_CONSUME_AGAIN : FunctionCodeEnum.LIBRA_CREDIT_CONSUME_LOAN;
	}

	@Override
	public TianchengDataDubboService getTianchengDataDubboService() {
		return tianchengDataDubboService;
	}

	@Override
	public UserForbidDubboService getUserForbidDubboService() {
		return userForbidDubboService;
	}
	
	/**
	 * 构建消费借用户信审请求参数
	 * 
	 * @param userId
	 * @param flowExecuteId
	 * @param project
	 * @param orderId
	 * @return
	 */
	private CreditAduitRequest bulidCreditAduitRequestParam(String userId, Long flowExecuteId, Project project, String orderId) {
        String projectId = String.valueOf(project.getProjectId());
        
		CreditAduitRequest creditAduitRequest = new CreditAduitRequest();
		
        // RCE公有参数        
		creditAduitRequest.setReserve(String.valueOf(flowExecuteId));
		creditAduitRequest.setTransNo(orderId);
		creditAduitRequest.setTransDate(new Date());
        
        // 授信相关参数
		creditAduitRequest.setOrder_id(orderId);
		creditAduitRequest.setProject_id(projectId);
		creditAduitRequest.setApply_amount(project.getContractAmount().doubleValue());
		creditAduitRequest.setFrom_source(AntifraudFromSourceEnum.CONSUME_LOAN.getFromSource());
		creditAduitRequest.setGps_province(project.getLoanProvince());
		creditAduitRequest.setGps_city(project.getLoanCity());
		creditAduitRequest.setGps_district(project.getLoanArea());
		creditAduitRequest.setNotify_url(TianchengModelParseService.buildNotifyUrl(webHttpUrl, TianchengCallbackEventEnum.SPEED_LOAN_AUDIT_POINT_FAKE, 
				projectId, getProjectType(), getFunctionCode()));
		creditAduitRequest.setIs_multi_borrow(0);
        
        // 用户信息（基础信息、工作信息、联系人信息）
        TianchengCreditBaseInfoResponseDTO tianchengCreditBaseInfoResponseDTO = tianchengDataDubboService.getUserTianchengCreditBaseInfo(userId);
        if (null != tianchengCreditBaseInfoResponseDTO) {
            BasicInfoDTO basicInfoDTO = tianchengCreditBaseInfoResponseDTO.getBaseInfo();
            WorkInfoDTO workInfoDTO = tianchengCreditBaseInfoResponseDTO.getWorkInfo();
            List<ContactPersonInfoDTO> contactPersonInfoDTOList = tianchengCreditBaseInfoResponseDTO.getContacts();
            if (null != basicInfoDTO) {
            	creditAduitRequest.setBasic_info(TianchengModelParseService.parseBaseInfo(basicInfoDTO));
            }
            if (null != workInfoDTO) {
            	creditAduitRequest.setWork_info(TianchengModelParseService.parseWorkInfo(workInfoDTO));
            }
            if (!CollectionUtils.isEmpty(contactPersonInfoDTOList)) {
            	creditAduitRequest.setContact_person(TianchengModelParseService.parseContactPersonInfo(contactPersonInfoDTOList));
            }
        }
		return creditAduitRequest;
	}
	
	/**
	 * 构建消费借复借用户信审请求参数
	 * 
	 * @param userId
	 * @param flowExecuteId
	 * @param project
	 * @param orderId
	 * @return
	 */
	private CreditAduitAgainRequest bulidCreditAduitAgainRequestParam(String userId, Long flowExecuteId, Project project, String orderId) {
        String projectId = String.valueOf(project.getProjectId());
        
		CreditAduitAgainRequest creditAduitAgainRequest = new CreditAduitAgainRequest();
		
        // RCE公有参数        
		creditAduitAgainRequest.setReserve(String.valueOf(flowExecuteId));
		creditAduitAgainRequest.setTransNo(orderId);
		creditAduitAgainRequest.setTransDate(new Date());
        
        // 授信相关参数
		creditAduitAgainRequest.setOrder_id(orderId);
		creditAduitAgainRequest.setProject_id(projectId);
		creditAduitAgainRequest.setApply_amount(project.getContractAmount().doubleValue());
		creditAduitAgainRequest.setFrom_source(AntifraudFromSourceEnum.CONSUME_LOAN.getFromSource());
		creditAduitAgainRequest.setNotify_url(TianchengModelParseService.buildNotifyUrl(webHttpUrl, TianchengCallbackEventEnum.SPEED_LOAN_AUDIT_POINT_FAKE, 
				projectId, getProjectType(), getFunctionCode()));
		creditAduitAgainRequest.setIs_multi_borrow(1);
		
        // 授权信息
        CreditScoreCardDTO creditScoreCardDTO = tianchengDataDubboService.queryCreditScoreCardParam(project.getBorrowUserId(), FunctionCodeEnum.LIBRA_CONSUME_LOAN.getHeadFunctionCode());
        creditAduitAgainRequest.setJd_auth(creditScoreCardDTO.getJd_auth());
        creditAduitAgainRequest.setJd_login_name(creditScoreCardDTO.getJd_login_name());
        creditAduitAgainRequest.setXx_auth(creditScoreCardDTO.getXx_auth());
        creditAduitAgainRequest.setYx_auth(creditScoreCardDTO.getYx_auth());
        creditAduitAgainRequest.setYx_entry_id(creditScoreCardDTO.getYx_entry_id());
        creditAduitAgainRequest.setYx_login_name(creditScoreCardDTO.getYx_login_name());
        
        // 用户信息（基础信息、工作信息、联系人信息）
        TianchengCreditBaseInfoResponseDTO tianchengCreditBaseInfoResponseDTO = tianchengDataDubboService.getUserTianchengCreditBaseInfo(userId);
        if (null != tianchengCreditBaseInfoResponseDTO) {
            BasicInfoDTO basicInfoDTO = tianchengCreditBaseInfoResponseDTO.getBaseInfo();
            WorkInfoDTO workInfoDTO = tianchengCreditBaseInfoResponseDTO.getWorkInfo();
            List<ContactPersonInfoDTO> contactPersonInfoDTOList = tianchengCreditBaseInfoResponseDTO.getContacts();
            if (null != basicInfoDTO) {
            	creditAduitAgainRequest.setBasic_info(TianchengModelParseService.parseBaseInfo(basicInfoDTO));
            }
            if (null != workInfoDTO) {
            	creditAduitAgainRequest.setWork_info(TianchengModelParseService.parseWorkInfo(workInfoDTO));
            }
            if (!CollectionUtils.isEmpty(contactPersonInfoDTOList)) {
            	creditAduitAgainRequest.setContact_person(TianchengModelParseService.parseContactPersonInfo(contactPersonInfoDTOList));
            }
        }
		return creditAduitAgainRequest;
	}	
}